﻿/*
 * Copyright (c) Martin Kinkelin
 *
 * See the "License.txt" file in the root directory for infos
 * about permitted and prohibited uses of this code.
 */

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.IO;

namespace Jarf
{
	/// <summary>
	/// Allows management of subfolders and files to be excluded
	/// from a backup task.
	/// </summary>
	public partial class ExcludedSourceItemsDialog : BaseDialog
	{
		string _sourceFolder;

		List<string> _items;



		/// <summary>
		/// Constructor.
		/// </summary>
		/// <param name="sourceFolder">Path of the source folder.</param>
		/// <param name="excludedItems">List of excluded items to be edited.</param>
		public ExcludedSourceItemsDialog(string sourceFolder, List<string> excludedItems)
		{
			if (!Directory.Exists(sourceFolder))
				throw new InvalidOperationException("The source folder does not exist.");
			if (excludedItems == null)
				throw new ArgumentNullException("excludedItems");

			_sourceFolder = sourceFolder;
			_items = excludedItems;

			InitializeComponent();

			listBox1.Items.AddRange(_items.ToArray());

			folderBrowserDialog1.SelectedPath = _sourceFolder;
			openFileDialog1.InitialDirectory = _sourceFolder;
		}


		private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
		{
			removeButton.Enabled = (listBox1.SelectedIndices.Count > 0);
		}

		private void removeButton_Click(object sender, EventArgs e)
		{
			if (MessageBox.Show("Are you sure you want to remove the selected exclusions?", "Confirmation",
				MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes)
				return;

			System.Collections.ArrayList selectedIndices =
				new System.Collections.ArrayList(listBox1.SelectedIndices);
			selectedIndices.Sort();

			for (int i = selectedIndices.Count - 1; i >= 0; --i)
			{
				listBox1.Items.RemoveAt((int)selectedIndices[i]);
			}

			HasChanged = true;
		}

		private void addFolderButton_Click(object sender, EventArgs e)
		{
			if (folderBrowserDialog1.ShowDialog(this) != DialogResult.OK)
				return;

			string subfolder = folderBrowserDialog1.SelectedPath;
			if (!IsInSourceFolder(subfolder))
			{
				MessageBox.Show("The selected folder is not a subfolder of the source folder.",
					"Invalid subfolder", MessageBoxButtons.OK, MessageBoxIcon.Error);

				folderBrowserDialog1.SelectedPath = _sourceFolder;

				return;
			}

			string relativeSubfolder = subfolder.Substring(_sourceFolder.Length);
			if (Path.DirectorySeparatorChar == '\\')
				relativeSubfolder = relativeSubfolder.Replace('\\', '/');

			listBox1.Items.Add(relativeSubfolder);

			HasChanged = true;
		}

		private void addFileButton1_Click(object sender, EventArgs e)
		{
			if (openFileDialog1.ShowDialog(this) != DialogResult.OK)
				return;

			List<string> relativeFiles = new List<string>(openFileDialog1.FileNames.Length);

			foreach (string file in openFileDialog1.FileNames)
			{
				if (!IsInSourceFolder(file))
				{
					MessageBox.Show("The selected file is not in the source folder.",
						"Invalid file", MessageBoxButtons.OK, MessageBoxIcon.Error);

					openFileDialog1.InitialDirectory = _sourceFolder;
					openFileDialog1.FileName = string.Empty;

					return;
				}

				string relativeFile = file.Substring(_sourceFolder.Length);
				if (Path.DirectorySeparatorChar == '\\')
					relativeFile = relativeFile.Replace('\\', '/');

				relativeFiles.Add(relativeFile);
			}

			openFileDialog1.InitialDirectory = Path.GetDirectoryName(openFileDialog1.FileName);
			openFileDialog1.FileName = string.Empty;

			listBox1.Items.AddRange(relativeFiles.ToArray());

			HasChanged = true;
		}


		private bool IsInSourceFolder(string path)
		{
			if (path.Length < _sourceFolder.Length + 2)
				return false;

			// use a case insensitive comparison under Windows
			return (string.Compare(path, 0, _sourceFolder, 0, _sourceFolder.Length, (Path.DirectorySeparatorChar == '\\')) == 0 &&
				path[_sourceFolder.Length] == Path.DirectorySeparatorChar);
		}


		protected override bool ApplyChanges()
		{
			_items.Clear();
			foreach (string item in listBox1.Items)
			{
				_items.Add(item);
			}

			return true;
		}
	}
}
